/*************************************************************************
    > File Name    : Configuration.cc
    > Author       : LiuLei
    > Mail         : 2261459486@qq.com 
    > Created Time : 2022年11月28日 星期一 11时44分23秒
 ************************************************************************/

#include "../../include/DictBuilder/Configuration.h"
#include <stdlib.h>
#include <unistd.h>
#include <new>
#include <iostream>
#include <fstream>
#include <sstream>
using std::nothrow;
using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;

// 饿汉模式，线程安全
Configuration *Configuration::_pInstance = Configuration::getInstance();
Configuration::AutoRelease Configuration::_autoRelease;

// 需要外部检查路径是否真实存在
string getPath(const string filename)
{
    Configuration *pConfig = Configuration::getInstance();
    return pConfig->_configMap[filename];
}

Configuration *Configuration::getInstance()
{
    if(nullptr == _pInstance)
    {
        // 拼装绝对路径，对项目的文件夹的位置有要求
        char *name = ::getenv("HOME");
        if(nullptr == name)
        {
            ::perror("::getenv in Configuration::getInstance()");
            ::exit(0);
        }
        string path(name);
        path += "/my-search-engine/conf/myconf.conf";
        _pInstance = new (nothrow) Configuration(path);
    }
    return _pInstance;
}

void Configuration::showConfig() const
{
    for(auto &it : _configMap)
    {
        cout << it.first << "  " << it.second << endl;
    }
}

unordered_map<string, string> &Configuration::getConfigMap()
{
    return _configMap;
}

unordered_set<string> Configuration::getStopWorlList() const
{
    return _stopWordList;
}

Configuration::AutoRelease::AutoRelease()
{

}

Configuration::AutoRelease::~AutoRelease()
{
    if(nullptr == _pInstance)
    {
        delete _pInstance;
        _pInstance = nullptr;
    }
}

Configuration::Configuration(const string &filePath)
: _filePath(filePath)
{
    //此处直接写死了路径，也可以通过传入的配置文件路径获取项目文件夹位置
    char *home = ::getenv("HOME");
    if(nullptr == home)
    {
        ::perror("::getenv in Configuration::Configuration()");
        ::exit(0);
    }

    string homestr(home);
    homestr += "/my-search-engine/";

    ifstream ifs(_filePath);
    if(!ifs.good())
    {
        cout << "Open " << _filePath << " error in Configuration::Configuration()!" << endl;
        return ;
    }

    string line;

    while(getline(ifs, line))
    {
        // 符号#是规定的注释符号，'\0'对应空行
        if('#' == line[0] || '\0' == line[0])
        {
            continue;
        }
        
        string key, value;
        istringstream iss(line);
        iss >> key >> value;
        if(0 == value.size() || !iss.eof())
        {
            ::perror("StopWordsFile error in Configuration::insertStopWords()");
            ifs.close();
            exit(0);
        }
        string path = homestr + value;
        _configMap[key] = path;
        line.clear();
    }

    ifs.close();
    initStopWords();
}

void Configuration::initStopWords()
{
    //若对应停用词文件存在则加载文件
    if(_configMap.find("stopwords-cn") != _configMap.end())
    {
        insertStopWords(_configMap["stopwords-cn"]);
    } 

    if(_configMap.find("stopwords-en") != _configMap.end())
    {
        insertStopWords(_configMap["stopwords-en"]);
    }
}

void Configuration::insertStopWords(const string &filePath)
{
    ifstream ifs;
    ifs.open(filePath);
    if(!ifs.good())
    {
        cout << "Open " << filePath << " error in Configuration::insertStopWords()!" << endl;
        ::exit(0);
    }

    string line;
    while(getline(ifs, line))
    {
        if('\0' == line[0])
        {
            continue;
        }
        istringstream iss(line);
        string word;
        iss >> word;
        if(0 == word.size() || !iss.eof())
        {
            ::perror("StopWordsFile error in Configuration::insertStopWords()");
            continue;
        }
        _stopWordList.insert(word);
        line.clear();
    }
    ifs.close();
}
